 
/*  wpvcon.c
    For use with tm40.c
    Stephen D. Anderson --- August 13, 1994

    Function to set range values, units, damping, and xfer function
    of primary variable.  It does the following.

    Checks for existence of field instrument.  Searches if necessary.

    Puts up menu and asks user which of 4 items to change or to quit.
    Repeats this until user selects quit.  If quit is selected, returns 
    to calling program.

    If new range values selected, user is asked to enter the units, upper 
    and lower range values.  These are then written to field instrum using 
    HART command 35.  Calls get_units() to present choice of units.

    If new display units selected, user is asked to select new units
    from table.  These are then written to field instrument using HART
    command 44.  Calls get_units() to present choice of units.

    If new damping is selected, user is asked to enter a damping
    value.  This is then written to field instrument using HART command 34.

    If new transfer function selected user is asked to between
    linear or square root.  Choice is then written to field instrum using
    HART command 47.


    ON ENTRY:   No arguments.

    ON EXIT:    Nothing is returned.

    REVISION LOG:


*/

#include "tm40.h"
#include "units.h"
#include "ieee.h"

void wpvcon()

{
    extern byte status1,status2;
    extern byte addr[];
    extern byte found;
    extern byte search(void);
    extern byte err(byte);
    extern byte err1(byte);
    extern void ieee(byte, byte *, float *);
    extern int hartcmd(byte *, byte, byte *, byte, byte *, byte);

    int i;
    byte j,s[20];
    int get_units();
    float f;

    /*  need field instr info?  */
    if (!found) found = search();
    if (!found) return;

    Wopen(5,10,15,70,2,WHITE|_BLUE,WHITE|_BLUE);
    while (1)   /*  get changes until quit. */
    {
        Wclear();
        WputCen("<< Select Desired Change for Primary Variable >>");
        delay(500); KeyClear();
        MnuAct(5);
        MnuItm(3,5,"Enter New Range Values",'A',1,ITM_BEF,NULL,NULL,NULL);
        MnuItm(4,5,"Enter New Display Units",'A',2,ITM_BEF,NULL,NULL,NULL);
        MnuItm(5,5,"Enter New Damping Value",'A',3,ITM_BEF,NULL,NULL,NULL);
        MnuItm(6,5,"Enter New Transfer Function",'A',4,ITM_BEF,NULL,NULL,NULL);
        MnuItm(7,5,"Quit",'A',5,ITM_BEF,NULL,NULL,NULL);
        MnuEnd(1,MNU_VER,20,1,WHITE|_BLACK,WHITE|_BLACK,
            WHITE|_BLACK,BLUE|_CYAN);
        i = MnuGet();

        /*  check for ESC.  */
        if (TcxlErr == W_ESCPRESS) i = 5;

        switch(i)
        {
            case 1: /*  Enter Range Values. */
            {
                /*  get the units. */
                Wopen(2,30,17,70,2,WHITE|_BLACK,WHITE|_BLACK);
                Wputs("\n\n    What are the units you want");
                Wputs("\n    For the Range Value entries?");
                Wputs("\n\n    Select Units From Table");
                Wputs("\n    at Left.  If you don't see");
                Wputs("\n    the units you want, select");
                Wputs("\n    'MORE UNITS' for the next");
                Wputs("\n    list of units.");

                Wopen(1,1,23,20,2,WHITE|_RED,WHITE|_RED);
                j = 0;
                while (( i = get_units(j)) == 200) j=0;

                /*  quit?  */
                if (i == -1)
                {
                    Wclose(); Wclose(); break;
                }

                Wclose(); s[0] = i;
                Wopen(2,2,6,25,2,WHITE|_GREEN,WHITE|_GREEN);
                Wputf("\n  %s",units[i]);
                delay(1000); Wclose();

                /*  get the upper range value. */
                Wclear();
                Wputs("\n\n    Enter Upper Range Value:");
                Wputs("\n\n         ");
                KwScanf("%e", &f);

                /*  check for quit. */
                if (TcxlErr == W_ESCPRESS)
                {
                    Wclose(); break;
                }

                CONVERT_TO_IEEE(&s[1], &f);  /*  convert it. */

                /*  get the lower range value. */
                Wclear();
                Wputs("\n\n   Enter Lower Range Value:");
                Wputs("\n\n        ");
                KwScanf("%e",&f);

                /*  check for quit.  */
                if (TcxlErr == W_ESCPRESS)
                {
                    Wclose(); break;
                }

                CONVERT_TO_IEEE(&s[5], &f);

                /*  write to field instrument. */
                i = hartcmd(s, 9, s, 9, addr, 35);

                /*  command succeed?  */
                if ((i & 1) != 0) 
                {
                    err1(35); Wclose(); break;
                }

                /*  correct number of received bytes?  */
                if ((i/256) != 9)
                {
                    /*  error.  */
                    err(35); Wclose(); break;
                }

                /*  report error or success.  */
                Wclear();
                if (status1 != 0)
                {
                    /*  error.  */
                    err(35);
                    WputCen("\n\nNew Range Values");
                    WputCen("\nmay not have been written");
                }
                else
                {
                    /*  success.  */
                    WputCen("\n\nNew Range Values Written");
                }
                WputCen("\n\nHit any key to resume.");
                KeyWait(); Wclose(); break;
            }
             
            case 2: /*  Enter New Display Units.  */
            {
                /*  get the units. */
                Wopen(2,30,17,70,2,WHITE|_BLACK,WHITE|_BLACK);
                Wputs("\n\n    What are the units you want");
                Wputs("\n    For the Primary Variable?");
                Wputs("\n    (These are the units that");
                Wputs("\n    the Field Instrument will send");
                Wputs("\n    along with the Primary Variable");
                Wputs("\n    value).");
                Wputs("\n\n    Select Units From Table");
                Wputs("\n    at Left.  If you don't see");
                Wputs("\n    the units you want, select");
                Wputs("\n    'MORE UNITS' for the next");
                Wputs("\n    list of units.");

                Wopen(1,1,23,20,2,WHITE|_RED,WHITE|_RED);
                j = 0;
                while (( i = get_units(j)) == 200) j=0;

                /*  quit?  */
                if (i == -1)
                {
                    Wclose(); Wclose(); break;
                }

                Wclose(); s[0] = i;
                Wopen(2,2,6,25,2,WHITE|_GREEN,WHITE|_GREEN);
                Wputf("\n  %s",units[i]);
                delay(1000); Wclose();

                /*  send units info to field instrument. */
                s[0] = i;
                i = hartcmd(s, 1, s, 1, addr, 44);

                /*  command succeed?  */
                if ((i & 1) != 0) 
                {
                    err1(44); Wclose(); break;
                }

                /*  correct number of received bytes?  */
                if ((i/256) != 1)
                {
                    /*  error.  */
                    err(44); Wclose(); break;
                }

                /*  report success or error.  */
                Wclear();
                if (status1 != 0)
                {
                    /*  error.  */
                    err(44);
                    WputCen("\n\nNew Units may");
                    WputCen("\nnot have been written.");
                }
                else
                {
                    /*  success.  */
                    WputCen("\n\nNew Units Written");
                }
                WputCen("\n\nHit any key to resume.");
                KeyWait(); Wclose(); break;
            }

            case 3: /*  Enter Damping */
            {
                /*  get damping value.  */
                Wopen(2,30,17,70,2,WHITE|_BLACK,WHITE|_BLACK);
                Wputs("\n\n    Enter the Time Constant (in");
                Wputs("\n    Seconds) to use for the New");
                Wputs("\n    Damping Value.");
                Wputs("\n\n          : ");
                KwScanf("%e", &f);

                /*  check for quit. */
                if (TcxlErr == W_ESCPRESS)
                {
                    Wclose(); break;
                }

                CONVERT_TO_IEEE(s, &f);   /*  convert it.  */

                /*  send damping value to field instrument. */
                delay(1000);
                i = hartcmd(s, 4, s, 4, addr, 34);

                /*  command succeed?  */
                if ((i & 1) != 0)
                {
                    /*  didn't.  */
                    err1(34); Wclose(); break;
                }

                /*  correct number of received bytes?  */
                if ((i/256) != 4)
                {
                    /*  error.  */
                    err(34); Wclose(); break;
                }

                /*  report success or error.  */
                Wclear();
                if (status1 != 0)
                {
                    /*  error.  */
                    err(34);
                    WputCen("\n\nNew Damping may");
                    WputCen("\nnot have been written.");
                }
                else
                {
                    /*  success.  */
                    WputCen("\n\nNew Damping Written");
                }
                WputCen("\n\nHit any key to resume.");
                KeyWait(); Wclose(); break;
            }

            case 4: /*  Enter Transfer Function. */
            {
                /*  get xfer function.  */
                Wopen(2,30,17,70,2,WHITE|_BLACK,WHITE|_BLACK);
                WputCen("\n<<  Select Primary Variable  >>");
                WputCen("\n<<  Transfer Function  >>");
                MnuAct(2);
                MnuItm(3,5,"LINEAR",'A',1,ITM_BEF,NULL,NULL,NULL);
                MnuItm(4,5,"SQR ROOT",'B',2,ITM_BEF,NULL,NULL,NULL);
                MnuEnd(1,MNU_VER,20,1,WHITE|_BLACK,WHITE|_BLACK,
                    WHITE|_BLACK,BLUE|_CYAN);
                i = MnuGet();
                
                /*  check for quit. */
                if (TcxlErr == W_ESCPRESS)
                {
                    Wclose(); break;
                }

                /*  write it to field instrument.  */
                --i;
                i = hartcmd(&(byte)i, 1, s, 1, addr, 47);

                /*  command succeed?  */
                if ((i & 1) != 0)
                {
                    /*  didn't.  */
                    err1(47); Wclose(); break;
                }

                /*  correct number of received bytes?  */
                if ((i/256) != 1)
                {
                    /*  error.  */
                    err(47); Wclose(); break;
                }

                /*  report error or success.  */
                Wclear();
                if (status1 != 0)
                {
                    /*  error.  */
                    err(47);
                    WputCen("\n\nNew Transfer Function");
                    WputCen("\nmay not have been written.");
                }
                else
                {
                    /*  success.  */
                    WputCen("\n\nNew Transfer Function");
                    WputCen("\nWritten");
                }
                WputCen("\n\nHit any key to resume.");
                KeyWait(); Wclose(); break;
            }

            case 5: /*  Quit. */
            {
                Wclose(); return;
            }
        }
    }
}

int get_units(byte j)

/*  Function displays a menu of units names for the user to select from.  It
    displays 20 choices.  A 21st choice of "more units" is included.  If the 
    user selects "more units", then the function calls itself to display 
    the next 20 choices.  This is repeated until j is greater than or equal
    to 200.  Once j reaches 200, the 21st menu choice becomes "start again"
    so that the user can search through the choices again.

    ON ENTRY:   "j" is an index to the first of the next 20 table values to 
                be displayed.  

    ON EXIT:    an integer corresponding to the units choice in array
                "units" is returned.  A -1 is returned if the ESC key
                was pressed.

    REVISION LOG:
*/

{
    byte i,k,jstart;

    /*  save starting value of j. */
    jstart = j;

    /*  present the next 20 table values. */
    Wclear();
    MnuAct(21);
    for (k=0; k<20; ++k)
    {
        MnuItm(k,0,units[j++],'A',k,ITM_BEF,NULL,NULL,NULL);
    }

    if (j != 200)   /*  done with all table values? */
    {
        /*  no, so display "more units" as one of the choices. */
        MnuItm(20,0,"MORE UNITS",'A',20,ITM_BEF,NULL,NULL,NULL);
    }
    else
    {
        /*  else display a line to allow another start. */
        MnuItm(20,0,"START AGAIN",'A',20,ITM_BEF,NULL,NULL,NULL);
    }

    /*  get the choice. */
    MnuEnd(0,MNU_VER,25,1,WHITE|_RED,WHITE|_RED,
        WHITE|_RED,BLUE|_CYAN);
    i = MnuGet();

    /*  check for quit. */
    if (TcxlErr == W_ESCPRESS)  return(-1);

    /*  if "more units" chosen, call function again. */
    if ((i == 20) && (j != 200))
    {
        i = get_units(j);
        return(i);
    }

    /*  at last of recursive calls, return the index to the units table. */
    return(jstart + i);
}

